using System;
using System.ComponentModel;

namespace ValidationFramework.ActiveRecord
{
    /// <summary>
    /// Provides base class that developer can (optionally) inherit from to provide <see cref="INotifyPropertyChanged"/> and <see cref="IDataErrorInfo"/> functionality for all sub-classes.
    /// </summary>
    /// <remarks>
    /// This ideal for windows forms applications to get immediate validation feedback on data bound controls.
    /// </remarks>
    [Serializable]
    public abstract class ActiveRecordNotifyValidatableBase<T> : ActiveRecordDataErrorInfoValidatableBase<T>, INotifyPropertyChanged
    {

        #region Methods

        /// <summary>
        /// Perform validation and <see cref="INotifyPropertyChanged"/> functionality for specified property.
        /// </summary>
        /// <param name="propertyName">The name of the property to validate.  The parameter is case sensitive.</param>
        protected void NotifyAndValidate(string propertyName)
        {
            ValidateProperty(propertyName);
            NotifyPropertyChanged(propertyName);
            //TODO: should we fire a notify on isValid??
        }


        /// <summary>
        /// Performs INotifyPropertyChanged functionality for specified property.
        /// </summary>
        /// <param name="propertyName">The name of the property that has changed. The parameter is case sensitive.</param>
        protected void NotifyPropertyChanged(string propertyName)
        {
            OnPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }


        /// <summary>
        /// Raises the <see cref="PropertyChanged"/> event.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A <see cref="PropertyChangedEventArgs"/> that contains the event data.</param>
        protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (propertyChanged != null)
            {
                propertyChanged(sender, e);
            }
        }

        #endregion


        #region Properties

        //TODO: work out how to make this not serialize. 
        //[field:NonSerialized]
        private event PropertyChangedEventHandler propertyChanged;

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        /// <remarks>
        /// The <see cref="PropertyChanged"/> event can indicate all properties on the object have changed by using either a null reference or <see cref="String.Empty"/> as the <see cref="PropertyChangedEventArgs.PropertyName"/> in the <see cref="PropertyChangedEventArgs"/>.
        /// </remarks>
        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                propertyChanged += value;
            }
            remove
            {
                propertyChanged -= value;
            }
        }


        #endregion
    }
}